﻿/**
 * This is our resource manager. 
 * This Class receives a .zip file and loads in all the images from this
 * file into the ram memory.
 * 
 * The purpose of this is to allow us to query the files from ram rather than from the harddrive.
 * This will be alot faster and make sure we dont get annoying lag everytime we make a new enemy 
 * (every enemy needs a image that we use to portray it in the game).
 * 
 * The file starts out by reading xml files in the .zip file, this zip file contains instructions
 * on what the RM should load. New images that we want to use in the game need to be added
 * to this .xml file.
 **/

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using AgateLib.DisplayLib;
using AgateLib.Sprites;
using Ionic.Zip;

namespace AiAsteriods.Game.Tools {
  class ResourceManager {
    private string datapath;
    private String baseSpritePath = "resources/graphics/";

    private Dictionary<string, Sprite> cachedSprites = null;
    private Dictionary<string, Stream> cachedDataFiles = null;

    public ResourceManager(int size, string datapath) {
      this.datapath = datapath;

      if (size < 1)
        size = 1;

      cachedSprites = new Dictionary<string,Sprite>(size);
      cachedDataFiles = new Dictionary<string, Stream>(size);

      CacheSprites();

      Console.WriteLine(cachedSprites.Count + " cached Sprites");
      foreach (string key in cachedSprites.Keys) {
        Console.WriteLine(" \t " + key);
      }
    }
    
    public Sprite GetSprite(String name) {
      if (cachedSprites.ContainsKey(name)) {
        return cachedSprites[name].Clone();
      }
      return null;
    }

    private void CacheSprites() {
      using (ZipFile zip1 = ZipFile.Read(datapath)) {
        foreach (ZipEntry e in zip1) {
          if (!e.IsDirectory && e != null) {
            Stream s = new MemoryStream();
            e.Extract(s);
            String[] ste = e.ToString().Split(':');
            cachedDataFiles.Add(ste[ste.Length - 1], s);
            Console.WriteLine("Caching: " + ste[ste.Length - 1]);
          }
        }
      }

      // find the xml file in the data file
      Stream xmlstream = null;
      foreach (string key in cachedDataFiles.Keys) {
        if (key.Contains(".xml")) {
          xmlstream = cachedDataFiles[key];

          if (xmlstream != null) {

            Console.WriteLine("reading xml file: " + key.ToString() + "\r\n" + xmlstream.ToString());
            ReadXMLConfig(xmlstream);
          }
        }
      }
    }

    // read in and deal with data in xml file
    private void ReadXMLConfig(System.IO.Stream xmlstream) {
      XmlDocument doc = new XmlDocument();
      xmlstream.Position = 0;
      doc.Load(xmlstream);

      XmlNodeList nList1 = doc.SelectNodes("root");

      foreach (XmlNode objNode1 in nList1) {
        XmlNodeList nList2 = objNode1.SelectNodes("sprites");
        foreach (XmlNode objNode2 in nList2) {
          XmlNodeList nList3 = objNode2.SelectNodes("sprite");
          foreach (XmlNode objNode3 in nList3) {

            String spriteName = objNode3.SelectSingleNode("name").InnerText.ToString();
            String tempResolution = objNode3.SelectSingleNode("size").InnerText.ToString();
            String image = objNode3.SelectSingleNode("path").InnerText.ToString();

            String[] res = tempResolution.Split(',');

            int width = int.Parse(res[0]);
            int height = int.Parse(res[1]);

            String spritePath = baseSpritePath + image;

            Stream imageStream = null;
            Sprite tempSprite = null;
            Surface tempSurface = null;
            imageStream = cachedDataFiles[spritePath];
            if (imageStream != null) {
              tempSurface = new Surface(imageStream);

              /* try to make sure the surface is read in and not waiting to read from stream */
              tempSurface.ReadPixels();
              tempSurface.ToString();

              tempSprite = new Sprite(tempSurface, true, width, height);
              cachedSprites.Add(spriteName, tempSprite);
            }
          }
        }
      }
    }
  }
}